﻿using Newtonsoft.Json;
using SqlSugar;
using SupDataSync.Common;
using SupDataSync.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using DataSyncCommon;

namespace SupDataSync.ChildForms
{
    /// <summary>
    /// 基础数据同步
    /// </summary>
    public partial class FrmBaseDataSync : Form
    {
        private string CustomerCode { get; set; }
        private string SupplierId { get; set; }
        private DataTable DataSource { get; set; }

        public FrmBaseDataSync()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmBaseDataSync_Load(object sender, EventArgs e)
        {
            this.dgView_BaseTable.AutoGenerateColumns = false;
        }

        /// <summary>
        /// 窗体显示事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmBaseDataSync_Shown(object sender, EventArgs e)
        {
            try
            {
                string sql = "select t.customercode,t.custormername from ba_customer t where t.isused=1 " +
                    "and t.customercode not in (20520001,20510002) order by t.customercode desc";//贵州四川 and t.customercode not in (20520001,20510002)";
                DataSet ds_customer = null;
                DbHelperMySql.ExecuteQuery(sql, out ds_customer);
                if (ds_customer != null && ds_customer.Tables.Count > 0 && ds_customer.Tables[0].Rows.Count > 0)
                {
                    this.cmb_Customer.DataSource = ds_customer.Tables[0];
                    this.cmb_Customer.DisplayMember = "custormername";
                    this.cmb_Customer.ValueMember = "customercode";

                    InitSupList(this.cmb_Customer.SelectedValue + "");
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, "提示");
            }
        }

        /// <summary>
        /// 选择客户事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmb_Customer_SelectedIndexChanged(object sender, EventArgs e)
        {
            string customerCd = this.cmb_Customer.SelectedValue + "";
            InitSupList(customerCd);
        }

        private void InitSupList(string customerCd)
        {
            this.cmb_Sup.DataSource = null;
            var sql = @"select t.SYS_ID_KEY,t.SYS_CD_NM from ba_supplier t where t.SYS_USE_MARK=1 and t.Customercode='{0}'
and t.SYS_ID_KEY in (select DISTINCT t.SUP_ID from pp_big_lab_sup t where t.CUSTOMERCODE = '{0}')";
            sql = string.Format(sql, customerCd);
            DataSet ds_sup = null;
            DbHelperMySql.ExecuteQuery(sql, out ds_sup);
            if (ds_sup != null && ds_sup.Tables.Count > 0 && ds_sup.Tables[0].Rows.Count > 0)
            {
                this.cmb_Sup.DataSource = ds_sup.Tables[0];
                this.cmb_Sup.DisplayMember = "SYS_CD_NM";
                this.cmb_Sup.ValueMember = "SYS_ID_KEY";
            }
        }

        /// <summary>
        /// 查询事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Query_Click(object sender, EventArgs e)
        {
            Query();
        }

        /// <summary>
        /// 查询方法
        /// </summary>
        private void Query()
        {
            DataSource = null;
            this.dgView_BaseTable.DataSource = null;
            CustomerCode = "";
            SupplierId = "";

            var customerCd = this.cmb_Customer.SelectedValue + "";
            var supId = this.cmb_Sup.SelectedValue + "";
            string sql = @"select 2 as seq,'客户信息' as businame,'ba_customer' as tablename,count(*) as rowcount,c.custormername,c.customercode from ba_customer c where c.customercode='{0}' and c.isused=1
group by c.custormername,c.customercode
union all
select 1 as seq,'供应商信息' as businame,'ba_supplier',count(*) as rowcount,'' as custormername,s.Customercode from ba_supplier s where s.Customercode='{0}' and s.SYS_ID_KEY='{1}'
union all
select 3 as seq,'物料类型' as businame,'ba_material_type',count(*) as rowcount,'' as custormername,t.CUSTOMERCODE from ba_material_type t where t.CUSTOMERCODE='{0}' and t.SYS_USE_MARK=1
union all
select 4 as seq,'物料' as businame,'ba_material',count(*) as rowcount,'' as custormername,m.CUSTOMERCODE from ba_material m 
left join ba_material_type t on m.MAT_TYPE_ID=t.SYS_USER_CD and m.CUSTOMERCODE=t.CUSTOMERCODE
where m.CUSTOMERCODE='{0}' and m.SYS_USE_MARK=1 and t.SYS_USE_MARK=1
union all
select 5 as seq,'计量单位' as businame,'ba_unit',count(*) as rowcount,'' as custormername,u.CUSTOMERCODE from ba_unit u where u.CUSTOMERCODE='{0}'
union all
select 6 as seq,'条码规则名称' as businame,'ba_name_define',count(*) as rowcount,'' as custormername,'' from ba_name_define n
union all
select 7 as seq,'条码标识' as businame,'ba_bar_flag',count(*) as rowcount,'' as custormername,b.CUSTOMERCODE from ba_bar_flag b
left join ba_material_type t on b.MATERIAL_TYPE_ID=t.SYS_USER_CD and b.CUSTOMERCODE=t.CUSTOMERCODE
 where b.CUSTOMERCODE='{0}' and t.SYS_USE_MARK=1 and b.SUPPLIER_ID='{1}'
union all
select 8 as seq,'计量单位转换' as businame,'ba_mat_unit_chg',count(*) as rowcount,'' as custormername,uc.CUSTOMERCODE from ba_mat_unit_chg uc
left join ba_material m on uc.MAT_ID=m.SYS_ID_KEY and m.CUSTOMERCODE=uc.CUSTOMERCODE
left join ba_material_type t on m.MAT_TYPE_ID=t.SYS_USER_CD and m.CUSTOMERCODE=t.CUSTOMERCODE
where uc.CUSTOMERCODE='{0}' and t.SYS_USE_MARK=1 and m.SYS_USE_MARK=1
union all
select 9 as seq,'条码规则主表' as businame,'ba_bar_version',count(*) as rowcount,'' as custormername,v.CUSTOMERCODE from ba_bar_version v where v.CUSTOMERCODE='{0}'
union all
select 10 as seq,'条码规则明细表' as businame,'ba_bar_ruledetail',count(*) as rowcount,'' as custormername,r.CUSTOMERCODE from ba_bar_ruledetail r where r.CUSTOMERCODE='{0}'";

            sql = string.Format(sql, customerCd, supId);
            DataSet ds;
            DbHelperMySql.ExecuteQuery(sql, out ds);
            if (ds != null && ds.Tables.Count > 0)
            {
                CustomerCode = customerCd;
                SupplierId = supId;

                var dt = ds.Tables[0];
                dt.Columns.Add("supid", Type.GetType("System.String"));
                dt.Columns.Add("syncmsg", Type.GetType("System.String"));
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    dt.Rows[i]["supid"] = supId;
                    dt.Rows[i]["syncmsg"] = "";
                    dt.Rows[i]["custormername"] = dt.Rows[0]["custormername"];
                }
                dt.DefaultView.Sort = "seq asc";
                DataSource = dt;
                this.dgView_BaseTable.DataSource = dt;
                ShowMsg("客户的id：" + customerCd + "，供应商的id：" + supId);
            }

        }

        /// <summary>
        /// 同步事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgView_BaseTable_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                if (e.ColumnIndex != 5)
                    return;

                try
                {
                    ClearSyncInfo();

                    DataGridViewColumn column = dgView_BaseTable.Columns[e.ColumnIndex];
                    if (column is DataGridViewButtonColumn)
                    {
                        var tablename = dgView_BaseTable.Rows[e.RowIndex].Cells["tablename"].Value.ToString();
                        var customercd = dgView_BaseTable.Rows[e.RowIndex].Cells["customercode"].Value.ToString();
                        var supid = dgView_BaseTable.Rows[e.RowIndex].Cells["supid"].Value.ToString();
                        SyncBaseData(tablename, customercd, supid);
                    }
                }
                catch(Exception err)
                {
                    MessageBox.Show(err.Message, "提示");
                }
            }
        }

        /// <summary>
        /// 同步单个表
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="customercd"></param>
        /// <param name="supid"></param>
        private void SyncBaseData(string tablename, string customercd, string supid)
        {
            var model = new SyncBaseModel();
            model.CustomerCode = customercd;
            model.TenantId = SysConfig.TenantId;
            using (var db = DbHelperMySql.GetSqlSugarDb())
            {
                switch(tablename)
                {
                    case "ba_customer":
                        model.CustomerList = db.Queryable<ba_customer>()
                            .Where(p => p.customercode == customercd && p.isused == 1)
                            .ToList();
                        break;
                    case "ba_supplier":
                        model.SupplierList = db.Queryable<ba_supplier>()
                            .Where(p => p.Customercode == customercd && p.SYS_ID_KEY == supid)
                            .ToList();
                        break;
                    case "ba_material_type":
                        model.MatTypeList = db.Queryable<ba_material_type>()
                            .Where(p => p.CUSTOMERCODE == customercd && p.SYS_USE_MARK == 1)
                            .OrderBy(p => p.SYS_ID_KEY)
                            .ToList();
                        break;
                    case "ba_material":
                        model.MatList = db.Queryable<ba_material, ba_material_type>((m, t) => new object[]{
                            JoinType.Left, m.MAT_TYPE_ID == t.SYS_USER_CD && m.CUSTOMERCODE == t.CUSTOMERCODE })
                            .Where((m, t) => m.CUSTOMERCODE == customercd && m.SYS_USE_MARK == 1 && t.SYS_USE_MARK == 1)
                            .OrderBy((m, t) => m.SYS_ID_KEY)
                            .Select((m, t) => m)
                            .ToList();
                        break;
                    case "ba_unit":
                        model.UnitList = db.Queryable<ba_unit>()
                            .Where(p => p.CUSTOMERCODE == customercd)
                            .OrderBy(p => p.SYS_ID_KEY)
                            .ToList();
                        break;
                    case "ba_name_define":
                        model.NameDefineList = null;
                        break;
                    case "ba_bar_flag":
                        model.BarFlagList = db.Queryable<ba_bar_flag, ba_material_type>((b, t) => new object[]{
                                JoinType.Left, b.MATERIAL_TYPE_ID == t.SYS_USER_CD && b.CUSTOMERCODE == t.CUSTOMERCODE })
                            .Where((b, t) => b.CUSTOMERCODE == customercd && t.SYS_USE_MARK == 1 && b.SUPPLIER_ID == supid)
                            .OrderBy((b, t) => b.SYS_ID_KEY)
                            .ToList();
                        break;
                    case "ba_mat_unit_chg":
                        model.MatUntiChgList = db.Queryable<ba_mat_unit_chg, ba_material, ba_material_type>((u, m, t) => new object[]{
                                JoinType.Left, u.MAT_ID == m.SYS_ID_KEY && u.CUSTOMERCODE == m.CUSTOMERCODE,
                                JoinType.Left, m.MAT_TYPE_ID == t.SYS_USER_CD && m.CUSTOMERCODE == t.CUSTOMERCODE
                            }).Where((u, m, t) => u.CUSTOMERCODE == customercd && t.SYS_USE_MARK == 1 && m.SYS_USE_MARK == 1)
                            .OrderBy((u, m, t) => u.SYS_ID_KEY)
                            .ToList();
                        break;
                    case "ba_bar_version":
                        model.BarVersionList = db.Queryable<ba_bar_version>()
                            .Where(p => p.CUSTOMERCODE == customercd)
                            .OrderBy(p => p.VERSIONNO)
                            .ToList();
                        break;
                    case "ba_bar_ruledetail":
                        model.BarRuleDetail = db.Queryable<ba_bar_ruledetail>()
                            .Where(p => p.CUSTOMERCODE == customercd)
                            .OrderBy(p => p.VERSIONID)
                            .OrderBy(p => p.STARTPOSITION)
                            .ToList();
                        break;
                }
            }
            
            var url = SysConfig.SyncBaseApiUrl;
            var reqjson = JsonConvert.SerializeObject(model);
            var responseStr = HttpHelper.WebRequestApi(url, reqjson, "POST");
            var syncResultList = JsonConvert.DeserializeObject<List<SyncResultModel>>(responseStr);

            RefreshSyncResult(syncResultList, tablename);
        }

        /// <summary>
        /// 同步全部
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_SyncAll_Click(object sender, EventArgs e)
        {
            
            if (this.dgView_BaseTable.Rows.Count == 0)
            {
                MessageBox.Show("无数据，请先查询需要同步的表数据！","提示");
                return;
            }

            SyncBaseDataAll(CustomerCode, SupplierId);
        }

        /// <summary>
        /// 同步所有表
        /// </summary>
        /// <param name="customercd"></param>
        /// <param name="supid"></param>
        private void SyncBaseDataAll(string customercd, string supid)
        {
            try
            {
                var model = new SyncBaseModel();
                model.CustomerCode = customercd;
                model.TenantId = SysConfig.TenantId;

                //获取本地基础表数据
                using (var db = DbHelperMySql.GetSqlSugarDb())
                {
                    model.CustomerList = db.Queryable<ba_customer>()
                        .Where(p => p.customercode == customercd && p.isused == 1)
                        .ToList();

                    model.SupplierList = db.Queryable<ba_supplier>()
                        .Where(p => p.Customercode == customercd && p.SYS_ID_KEY == supid)
                        .ToList();

                    model.MatTypeList = db.Queryable<ba_material_type>()
                        .Where(p => p.CUSTOMERCODE == customercd && p.SYS_USE_MARK == 1)
                        .OrderBy(p => p.SYS_ID_KEY)
                        .ToList();

                    model.MatList = db.Queryable<ba_material, ba_material_type>((m, t) => new object[]{
                            JoinType.Left, m.MAT_TYPE_ID == t.SYS_USER_CD && m.CUSTOMERCODE == t.CUSTOMERCODE })
                        .Where((m, t) => m.CUSTOMERCODE == customercd && m.SYS_USE_MARK == 1 && t.SYS_USE_MARK == 1)
                        .OrderBy((m, t) => m.SYS_ID_KEY)
                        .Select((m, t) => m)
                        .ToList();

                    model.UnitList = db.Queryable<ba_unit>()
                        .Where(p => p.CUSTOMERCODE == customercd)
                        .OrderBy(p => p.SYS_ID_KEY)
                        .ToList();

                    model.BarFlagList = db.Queryable<ba_bar_flag, ba_material_type>((b, t) => new object[]{
                            JoinType.Left, b.MATERIAL_TYPE_ID == t.SYS_USER_CD && b.CUSTOMERCODE == t.CUSTOMERCODE })
                        .Where((b, t) => b.CUSTOMERCODE == customercd && t.SYS_USE_MARK == 1 && b.SUPPLIER_ID == supid)
                        .OrderBy((b, t) => b.SYS_ID_KEY)
                        .ToList();

                    model.MatUntiChgList = db.Queryable<ba_mat_unit_chg, ba_material, ba_material_type>((u, m, t) => new object[]{
                            JoinType.Left, u.MAT_ID == m.SYS_ID_KEY && u.CUSTOMERCODE == m.CUSTOMERCODE,
                            JoinType.Left, m.MAT_TYPE_ID == t.SYS_USER_CD && m.CUSTOMERCODE == t.CUSTOMERCODE
                        }).Where((u, m, t) => u.CUSTOMERCODE == customercd && t.SYS_USE_MARK == 1 && m.SYS_USE_MARK == 1)
                        .OrderBy((u, m, t) => u.SYS_ID_KEY)
                        .ToList();

                    model.BarVersionList = db.Queryable<ba_bar_version>()
                        .Where(p => p.CUSTOMERCODE == customercd)
                        .OrderBy(p => p.VERSIONNO)
                        .ToList();

                    model.BarRuleDetail = db.Queryable<ba_bar_ruledetail>()
                        .Where(p => p.CUSTOMERCODE == customercd)
                        .OrderBy(p => p.VERSIONID)
                        .OrderBy(p => p.STARTPOSITION)
                        .ToList();
                }

                var url = SysConfig.SyncBaseApiUrl;
                var reqjson = JsonConvert.SerializeObject(model);
                var responseStr = HttpHelper.WebRequestApi(url, reqjson, "POST");
                var syncResultList = JsonConvert.DeserializeObject<List<SyncResultModel>>(responseStr);

                //刷新同步结果
                RefreshSyncResult(syncResultList, "");

                ShowMsg("同步结束！");
            }
            catch(Exception err)
            {
                ShowMsg(err.Message);
                MessageBox.Show(err.Message, "提示");
            }
        }

        /// <summary>
        /// 刷新同步结果信息
        /// </summary>
        /// <param name="resultList"></param>
        /// <param name="syncTableName"></param>
        private void RefreshSyncResult(List<SyncResultModel> resultList, string syncTableName)
        {
            if (resultList == null || resultList.Count == 0)
            {
                MessageBox.Show("同步失败！", "提示");
                return;
            }

            #region 
            //for (var i = 0; i < this.dgView_BaseTable.Rows.Count; i++)
            //{
            //    var tablename = dgView_BaseTable.Rows[i].Cells["tablename"].Value.ToString();
            //    var result = resultList.Where(p => p.TableName == tablename).FirstOrDefault();
            //    if (result != null)
            //    {
            //        var msg = result.SyncSuccess.Value ? "同步成功！" : "同步失败！" + string.Format("插入[{1}],更新[{0}]", result.InsertCount, result.UpdateCount);
            //        dgView_BaseTable.Rows[i].Cells["syncmsg"].Value = msg;

            //        if (result.SyncSuccess.Value == false)
            //            dgView_BaseTable.Rows[i].Cells["syncmsg"].Style.BackColor = Color.Red;
            //    }
            //    else
            //    {
            //        if (!string.IsNullOrEmpty(syncTableName) && syncTableName != tablename)
            //            continue;

            //        dgView_BaseTable.Rows[i].Cells["syncmsg"].Value = "同步失败！";
            //        dgView_BaseTable.Rows[i].Cells["syncmsg"].Style.BackColor = Color.Red;
            //    }
            //}
            //dgView_BaseTable.Refresh();
            #endregion 

            for (var i = 0; i < this.DataSource.Rows.Count; i++)
            {
                var tablename = DataSource.Rows[i]["tablename"].ToString();
                var result = resultList.Where(p => p.TableName == tablename).FirstOrDefault();
                if (result != null)
                {
                    var msg = result.SyncSuccess.Value ? "同步成功！" + string.Format("插入[{0}],更新[{1}]", result.InsertCount, result.UpdateCount) : "同步失败！";
                    DataSource.Rows[i]["syncmsg"] = msg;
                }
                else
                {
                    if (!string.IsNullOrEmpty(syncTableName) && syncTableName != tablename)
                        continue;
                    if (tablename == "ba_name_define")
                    {
                        DataSource.Rows[i]["syncmsg"] = "暂时不需要";
                        continue;
                    }

                    DataSource.Rows[i]["syncmsg"] = "同步失败！";
                }
            }
            this.dgView_BaseTable.DataSource = null;
            this.dgView_BaseTable.DataSource = DataSource;


            var setForeignResult = resultList.Where(p => p.TableName == "ReSetBaseDataForeign").FirstOrDefault();
            if(setForeignResult!=null)
            {
                var msg = setForeignResult.SyncSuccess.Value ? "更新表关联成功！" : "更新表关联异常！";
                ShowMsg(msg + setForeignResult.SyncMsg);
            }

            var dumpToPubResult = resultList.Where(p => p.TableName == "DumpBaseDataToPub").FirstOrDefault();
            if (dumpToPubResult != null)
            {
                var msg = dumpToPubResult.SyncSuccess.Value ? "转储数据到PUB成功！" : "转储数据到PUB异常！";
                ShowMsg(msg + dumpToPubResult.SyncMsg);
            }

            var exceptionResult = resultList.Where(p => p.TableName == "Exception").FirstOrDefault();
            if (exceptionResult != null)
            {
                var msg = "同步过程发生异常！";
                ShowMsg(msg + exceptionResult.SyncMsg);
            }
            
        }

        /// <summary>
        /// 清除同步结果信息
        /// </summary>
        private void ClearSyncInfo()
        {
            this.lb_SyncMsg.Items.Clear();
            ShowMsg("同步开始……");
            
            for (var i = 0; i < this.dgView_BaseTable.Rows.Count; i++)
            {
                dgView_BaseTable.Rows[i].Cells["syncmsg"].Style.BackColor = Color.White;
            }

            for (var i = 0; i < this.DataSource.Rows.Count; i++)
            {
                DataSource.Rows[i]["syncmsg"] = "";
            }

            dgView_BaseTable.DataSource = null;
            dgView_BaseTable.DataSource = DataSource;

            this.Refresh();
        }

        /// <summary>
        /// 输出信息
        /// </summary>
        /// <param name="msg"></param>
        private void ShowMsg(string msg)
        {
            var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss   ");
            this.lb_SyncMsg.Items.Add(curTime + msg);
        }

        private void cmb_Sup_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void lb_SyncMsg_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("1.选择客户和企业，点击[查询]；" +
               "\n2.点击[同步全部]将全部数据进行同步；" +
               "\n3.选择单项点击[同步]，只同步的当前所选择的表；" +
               "\n4.下方可查看同步信息结果。", "帮助");
        }
    }
}
